package se.waltersson.wowarmory.page;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public abstract class ArmoryPage {
    private String charName;
    private String realm;
    
    private Document doc;
    private XPathFactory xpFactory;
    
    public ArmoryPage(String realm, String charName) {
        this.realm = realm;
        this.charName = charName;
    }
    
    public String getCharName() {
        return charName;
    }
    /**
     * Get the path part of the url used to retrieve this page.
     * 
     * @return The path including leading /
     */
    public abstract String getQuery();

    public String getQueryParameters() {
        String n = charName;
        try {
            n = URLEncoder.encode(n, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "?r=" + realm + "&n=" + n;
    }
    public void parse(Document doc) {
        this.doc = doc;
        xpFactory = XPathFactory.newInstance();
        parse();
    }
    
    protected abstract void parse();
    
    protected String getValue(String xpath)
        throws XPathExpressionException
    {
        XPathExpression pe = getXPathExpression(xpath);
        return pe.evaluate(doc);
    }

    protected long getNumber(String xpath)
        throws XPathExpressionException 
    {
        XPathExpression pe = getXPathExpression(xpath);
        return Long.parseLong(pe.evaluate(doc));
    }

    private XPathExpression getXPathExpression(String xpath)
        throws XPathExpressionException
    {
        XPath xp = xpFactory.newXPath();
        XPathExpression expr 
            = xp.compile(xpath);
        return expr;
    }
    
    protected Map<String, ParsedNode> getMap(String xpath,
        String keyAttr, NodeParser nodeParser)
    {
        Map<String, ParsedNode> map = new HashMap<String, ParsedNode>();
        XPathExpression pe;
        try {
            pe = getXPathExpression(xpath);
            NodeList nodes = (NodeList) pe.evaluate(doc,
                XPathConstants.NODESET);
            for (int i = 0; i < nodes.getLength(); i++) {
                Node node = nodes.item(i);
                NamedNodeMap attributes = node.getAttributes();
                String key = attributes.getNamedItem(keyAttr).getNodeValue();
                
                //String value = attributes.getNamedItem(valueAttr).getNodeValue();
                map.put(key, nodeParser.parseNode(node));
            }
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return map;
    }
}
